﻿using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Framework;
using Umbraco.Framework.Context;
using Umbraco.Framework.Persistence.Model;
using Umbraco.Framework.Persistence.Model.Associations;
using Umbraco.Framework.Persistence.Model.Associations._Revised;
using Umbraco.Framework.Persistence.Model.Attribution.MetaData;
using Umbraco.Framework.Persistence.Model.Constants;
using Umbraco.Framework.Persistence.ProviderSupport._Revised;
using Umbraco.Hive.ProviderSupport;
using WebGarden.Hive.Providers.Products.Schema.Model;


namespace WebGarden.Hive.Providers.Products.Schema
{
	/// <summary>
	/// 
	/// </summary>
	public class Repository: AbstractSchemaRepository
	{
		public Repository(ProviderMetadata providerMetadata, IFrameworkContext frameworkContext)
			: base(providerMetadata, frameworkContext)
		{ }

		#region Properties

		/// <summary>
		/// Gets a value indicating whether this instance can read relations.
		/// </summary>
		/// <value>
		/// <c>true</c> if this instance can read relations; otherwise, <c>false</c>.
		/// </value>
		public override bool CanReadRelations { get { return true; } }

		/// <summary>
		/// Gets a value indicating whether this instance can write relations.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance can write relations; otherwise, <c>false</c>.
		/// </value>
		public override bool CanWriteRelations { get { return false; } }

		#endregion

		#region Schema

		/// <summary>
		/// Identifies if a <see cref="!:TEntity"/> with matching <paramref name="id"/> can be found in this repository.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="id">The id.</param>
		/// <returns>
		///   <code>
		/// true
		/// </code>
		/// if the item with <paramref name="id"/> can be found, otherwise
		/// <code>
		/// false
		/// </code>
		/// .
		/// </returns>
		public override bool Exists<TEntity>(HiveId id)
		{
			return Get<TEntity>(true, id).Any();
		}

		/// <summary>
		/// Performs the add or update.
		/// </summary>
		/// <param name="entity">The entity.</param>
		public override void PerformAddOrUpdate(AbstractSchemaPart entity)
		{
			return;
		}

		/// <summary>
		/// Deletes the specified id.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="id">The id.</param>
		public override void Delete<T>(HiveId id)
		{
			return;
		}

		/// <summary>
		/// Performs the get.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="allOrNothing">if set to <c>true</c> [all or nothing].</param>
		/// <param name="ids">The ids.</param>
		/// <returns></returns>
		protected override IEnumerable<T> PerformGet<T>(bool allOrNothing, params HiveId[] ids)
		{
			// In the Wordpress hive provider there are two schemas with integer ids, i.e. 1 for PostSchema and 2 for CategorySchema
			//foreach (var hiveId in ids.Where(x => x.Value.Type == HiveIdValueTypes.Int32).Select(x => (int)x.Value))
			//{
			//    if (hiveId == 1)
			//        yield return new PostSchema() as T;
			//    else if (hiveId == 2)
			//        yield return new CategorySchema() as T;
			//}

			// In our provider there is only one schema, i.e. ProductSchema, whose hiveId is an integer (i.e. 1)
			foreach (var hiveId in ids.Where(x => x.Value.Type == HiveIdValueTypes.Int32).Select(x => (int)x.Value))
			{
				yield return new ProductSchema() as T;
			}
		}

		/// <summary>
		/// Performs the get all.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <returns></returns>
		public override IEnumerable<TEntity> PerformGetAll<TEntity>()
		{
			// There is only one schema in this provider, i.e. Product
			yield return new ProductSchema() as TEntity;
		}


		#endregion

		#region Relations

		/// <summary>
		/// Adds the relation.
		/// 
		/// Note that most of these methods throw NotImplementedException exceptions. This is because in our simple
		/// Products provider there are no relations defined. Take a look at the Wordpress provider to see how this is 
		/// implemented for the relationships between Wordpress blog posts and categories.
		/// </summary>
		/// <param name="item">The item.</param>
		public override void AddRelation(IReadonlyRelation<IRelatableEntity, IRelatableEntity> item)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Removes the relation.
		/// </summary>
		/// <param name="item">The item.</param>
		public override void RemoveRelation(IRelationById item)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Performs the get parent relations.
		/// </summary>
		/// <param name="childId">The child id.</param>
		/// <param name="relationType">Type of the relation.</param>
		/// <returns></returns>
		public override IEnumerable<IRelationById> PerformGetParentRelations(HiveId childId, RelationType relationType = null)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Performs the get child relations.
		/// </summary>
		/// <param name="parentId">The parent id.</param>
		/// <param name="relationType">Type of the relation.</param>
		/// <returns></returns>
		public override IEnumerable<IRelationById> PerformGetChildRelations(HiveId parentId, RelationType relationType = null)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Performs the get ancestor relations.
		/// </summary>
		/// <param name="descendentId">The descendent id.</param>
		/// <param name="relationType">Type of the relation.</param>
		/// <returns></returns>
		public override IEnumerable<IRelationById> PerformGetAncestorRelations(HiveId descendentId, RelationType relationType = null)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Performs the get descendent relations.
		/// </summary>
		/// <param name="ancestorId">The ancestor id.</param>
		/// <param name="relationType">Type of the relation.</param>
		/// <returns></returns>
		public override IEnumerable<IRelationById> PerformGetDescendentRelations(HiveId ancestorId, RelationType relationType = null)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Performs the find relation.
		/// </summary>
		/// <param name="sourceId">The source id.</param>
		/// <param name="destinationId">The destination id.</param>
		/// <param name="relationType">Type of the relation.</param>
		/// <returns></returns>
		public override IRelationById PerformFindRelation(HiveId sourceId, HiveId destinationId, RelationType relationType)
		{
			throw new NotImplementedException();
		}

		#endregion

		/// <summary>
		/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
		/// </summary>
		protected override void DisposeResources()
		{
			return;
		}

	}
}
